#region License

// This file is part of Grawlix.
// 
// Grawlix is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
// Grawlix is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public
// License along with Grawlix.  If not, see
// <http://www.gnu.org/licenses/>.

#endregion

using System;
using System.Diagnostics.CodeAnalysis;
using C5;
using Castle.Core;
using Castle.Windsor;

namespace Grawlix.Services
{
	/// <summary>
	/// A service, domain, and resource provider.
	/// </summary>
	public interface IGameKernel : IServiceProviderEx
	{
		/// <summary>
		/// Gets the list of all the <see cref="Domain"/> objects.
		/// </summary>
		/// <value>
		/// An immutable list of all the loaded <see cref="Domain"/>
		/// objects.
		/// </value>
		IList<Domain> Domains { get; }

		/// <summary>
		/// Gets any failure that occurred during game load.
		/// </summary>
		/// <value>The failure that occurred during loading, or null if
		/// there is no failure.</value>
		Exception Failure { get; }

		/// <summary>
		/// Gets the main controlling domain for this game.
		/// </summary>
		/// <value>The main controlling domain.</value>
		Domain Main { get; }

		/// <summary>
		/// Gets the kernel name.
		/// </summary>
		/// <value>A name for the kernel.</value>
		string Name { get; }

		/// <summary>
		/// Gets a value indicating whether this 
		/// <see cref="GameKernel"/> is finished loading.
		/// </summary>
		/// <value><c>true</c> if finished loading; otherwise, 
		/// <c>false</c>.
		/// </value>
		/// <remarks>The fact that it has finished loading could
		/// indicate a failure to load.</remarks>
		bool Ready { get; }

		/// <summary>
		/// Gets the <see cref="IWindsorContainer"/> that locates
		/// services.
		/// </summary>
		/// <value>The <see cref="IWindsorContainer"/> used to locate
		/// the services.
		///</value>
		IWindsorContainer WindsorContainer { get; }

		/// <summary>
		/// Reloads the resource from disk.
		/// </summary>
		/// <param name="resource">The resource to reload.</param>
		void ReloadResource<T>(T resource)
			where T : IDynamicResource;

		/// <summary>
		/// Finds or loads a domain with the specified name.
		/// </summary>
		/// <returns>The domain, which may not yet be loaded.</returns>
		/// <exception cref="ArgumentNullException"><c>name</c> is
		/// null.</exception>
		Domain ResolveDomain(string name);

		/// <summary>
		/// Finds or creates a resource with the specified identifier.
		/// </summary>
		/// <typeparam name="T">The type of resource to resolve.
		/// </typeparam>
		/// <param name="identifier">The identifier of the resource.
		/// </param>
		/// <returns>The resolved resource, which may not be ready for
		/// use.</returns>
		[SuppressMessage("Microsoft.Design", "CA1004",
			Justification =
				"A generic parameter provides type safety.")]
		T ResolveResource<T>(Uri identifier)
			where T : IDynamicResource;

		/// <summary>
		/// Finds a service of the given type.
		/// </summary>
		/// <typeparam name="T">The type of service to request.
		/// </typeparam>
		/// <returns>The requested service.</returns>
		[SuppressMessage("Microsoft.Design", "CA1004",
			Justification =
				"A generic parameter provides type safety.")]
		T ResolveService<T>();

		/// <summary>
		/// Finds a service of the given type, with the given key.
		/// </summary>
		/// <typeparam name="T">The type of service to request.
		/// </typeparam>
		/// <param name="key">The key of the service requested.</param>
		/// <returns>The requested service.</returns>
		[SuppressMessage("Microsoft.Design", "CA1004",
			Justification =
				"A generic parameter provides type safety.")]
		T ResolveService<T>(string key);

		/// <summary>
		/// Finds a service with the given key.
		/// </summary>
		/// <param name="key">The key of the service requested.</param>
		/// <returns>The requested service.</returns>
		object ResolveService(string key);

		/// <summary>
		/// Finds a service of the given type.
		/// </summary>
		/// <param name="service">The type of service requested.
		/// </param>
		/// <returns>The requested service.</returns>
		object ResolveService(Type service);

		/// <summary>
		/// Finds a service of the given type, with the given key.
		/// </summary>
		/// <param name="key">The key of the service requested.</param>
		/// <param name="service">The type of service requested.
		/// </param>
		/// <returns>The requested service.</returns>
		object ResolveService(string key, Type service);
	}
}